#pragma once

#include<iostream>
#include<sys/types.h>
#include<cstdlib>
#include<cstring>
#include<arpa/inet.h>
#include<sys/wait.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<pthread.h>
#include<signal.h>
#include"ThreadPool.hpp"
#include"Log.hpp"
#include"Task.hpp"
#include"Init.hpp"
#include"daemon.hpp"

extern Log lg;
const int defaultfd = -1;
const std::string defaultip = "0.0.0.0";
const int backlog = 5;   //一般不要设置太大

enum{
    UsageError = 1,
    SocketError = 2,
    BindError = 3,
    ListenError = 4
};

//class TcpServer;
// class ThreadData
// {
// public:
//     ThreadData(int fd ,const std::string& ip,const uint16_t& port, TcpServer* t)
//     :sockfd(fd),
//     clientip(ip),
//     clientport(port),
//     tsvr(t)
//     {}
// public:
//     int sockfd;
//     std::string clientip;
//     uint16_t clientport;
//     TcpServer* tsvr;
// };

class TcpServer
{
public:
    TcpServer(const uint16_t& port,const std::string& ip = defaultip)
    :listensock_(defaultfd),
    port_(port),
    ip_(ip)
    {}
    void InitServer()
    {
        //1.创建socket
        listensock_ = socket(AF_INET,SOCK_STREAM,0);
        if(listensock_ < 0)
        {
            lg(Fatal,"create socket err,errno: %d,err string: %s",errno,strerror(errno));
            exit(2);
        }
        lg(Info,"create socket success,listensock_: %d",listensock_);

        int opt = 1;
        setsockopt(listensock_,SOL_SOCKET,SO_REUSEADDR|SO_REUSEPORT,&opt,sizeof(opt));
        //防止偶发性的服务器无法立即重启

        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(port_);
        inet_aton(ip_.c_str(),&(local.sin_addr));
        //local.sin_addr.s_addr = INADDR_ANY;

        //2.bind
        if(bind(listensock_,(struct sockaddr*)&local,sizeof(local)) < 0)
        {
            lg(Fatal,"bind error,errno: %d,err string: %s",errno,strerror(errno));
            exit(BindError);
        }
        lg(Info,"bind socket success,listensock_: %d",listensock_);

        //Tcp面向连接,服务器一般比较被动,一直处于一种等待连接到来的状态
        if(listen(listensock_,backlog) < 0)
        {
            lg(Fatal,"listen error,errno: %d,err string: %s",errno,strerror(errno));
            exit(ListenError);
        }
        lg(Info,"listen socket success,listensock_: %d",listensock_);
    }

    // static void* Routine(void* args)         //Routine方法不能有this指针
    // {
    //     pthread_detach(pthread_self());   //解绑,不用等待
    //     ThreadData* td = static_cast<ThreadData*> (args);
    //     td->tsvr->Service(td->sockfd,td->clientip,td->clientport);
    //     delete td;
    //     return nullptr;
    // }

    void Start()
    {
        Daemon();   //守护进程
        //signal(SIGPIPE,SIG_IGN);
        ThreadPool<Task>::GetInstance()->Start();

        //signal(SIGCHLD,SIG_IGN);
        lg(Info,"tcpServer is running ...");
        while(true)
        {
            //1.获取新连接
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            int sockfd = accept(listensock_,(struct sockaddr*)&client,&len);
            if(sockfd < 0)
            {
                lg(Warning,"accept error,errno: %d,err string: %s",errno,strerror(errno));
                continue;
            }
           
            char clientip[32];
            uint16_t clientport = htons(client.sin_port);
            inet_ntop(AF_INET,&(client.sin_addr),clientip,sizeof(clientip));

             //2.根据新连接来进行通信
            lg(Info,"get a new link...,sockfd: %d,client ip: %s,client port: %d",sockfd,clientip,clientport);

            //version 1(单进程)
            // Service(sockfd,clientip,clientport);


            //version2(多进程)
            // pid_t id = fork();
            // if(id == 0)
            // {
            //     close(listensock_);
            //     //child
            //     if(fork() > 0)   //孙子进程,一旦子进程退出,system领养,这样防止父进程长时间等待
            //     {
            //         exit(0);  
            //     }
            //     Service(sockfd,clientip,clientport);
            //     close(sockfd);
            //     exit(0);
            // }
            // close(sockfd);
            // //father
            // pid_t rid = waitpid(id,nullptr,0);
            // (void)rid;


            //version3(多线程)
            // ThreadData* td = new ThreadData(sockfd,clientip,clientport,this);
            // pthread_t tid;
            // pthread_create(&tid,nullptr,Routine,td);


            //version4(线程池版)
            Task t(sockfd,clientip,clientport);
            ThreadPool<Task>::GetInstance()->Push(t);

        }
    }

    // void Service(int sockfd,const std::string& clientip,const uint16_t& clientport)
    // {
    //     char buffer[4096];
    //     while(true)
    //     {
    //         ssize_t n = read(sockfd,buffer,sizeof(buffer));  //tcp是面向字节流的可以用read
    //         if(n > 0)
    //         {
    //             buffer[n] = 0;
    //             std::cout<<"client say# "<<buffer<<std::endl;
    //             std::string echo_string = "tcpserver echo#";
    //             echo_string += buffer;

    //             write(sockfd,echo_string.c_str(),echo_string.size());
    //         }

    //         else if(n = 0)
    //         {
    //             lg(Info,"%s:%d quit,server close sockfd: %d",clientport,clientip.c_str(),sockfd);
    //             break;
    //         }

    //         else
    //         {
    //             lg(Warning,"read error,sockfd: %d,client ip: %s,client port: %d",sockfd,clientip.c_str(),clientport);
    //             break;
    //         }
    //     }
        
    // }
    ~TcpServer()
    {}
private:
    int listensock_;
    uint16_t port_;
    std::string ip_;
};